Skip to content

Arrow Functions

Historically, functions in JavaScript have been written using the function keyword:

function exclaim(string) {
return string + '!';
}

In 2015, the language received an alternative syntax for creating functions: arrow functions. They look like this:

const exclaim = string => string + '!';

Arrow functions are inspired by lambda functions from other functional programming languages. Their main benefit is that they're much shorter and cleaner. Reducing "function clutter" may seem like an insignificant benefit, but it can really help improve readability when working with . For example:

const arr = ['hey', 'ho', 'let\'s go'];
// This:
arr
.map(function(string) {
return string + '!'
})
.join(' ');
// …Becomes this:
arr
.map(string => string + '!')
.join(' ');

Rules of arrow functions

Arrow functions might seem straightforward at first glance, but there are a few “gotchas” to be aware of. It's super common for folks to get tripped up by some of these rules.

Short-form vs. long-form

There are two types of arrow functions: short-form and long-form.

Here's the short-form:

const add1 = n => n + 1;

And here's the long-form:

const add1 = n => {
return n + 1;
};

We opt into the long form by adding curly braces ({ }) around the function body.

The fundamental difference between the two forms is this:

  • The short-form function's body must be a single expression. That expression will be automatically returned.
  • The long-form function's body can contain a number of statements. We need to manually specify the return.

In the previous lesson, “Statements vs. Expressions”, we covered the differences between statements and expressions. Understanding that distinction will make it much easier to understand what's going on with these two arrow-function forms.

With the short-form, our function body consists of a single expression, and that expression will be returned. This is sometimes called an “implicit” return, because there's no return keyword.

When we add the squiggly brackets ({ }), we create a block of statements. We can put as many statements as we want in there. We need to specify what should be returned using a return statement.

Interestingly, if we try to add the return keyword to the short-form syntax, we'll get a syntax error:

const add1 = n => return n + 1;
// Uncaught SyntaxError: Unexpected token 'return'

Why is this an error? Well, return n + 1 is a statement, not an expression. The short form requires an expression. We're not allowed to put a statement there.

Optional parameter parentheses

If an arrow function takes a single parameter, the parentheses are optional:

// This is valid:
const logUser = user => {
console.log(user);
}
// This is also valid:
const logUser = (user) => {
console.log(user);
}

The parentheses are mandatory if we have more than 1 parameter:

const updateUser = (user, properties, isAdmin) => {
if (!isAdmin) {
throw new Error('Not authorized')
}
user.setProperties(properties);
}

The parentheses are also mandatory if we have no parameters:

const sayHello = () => console.log('Hello!')

Sugar-free functions

In JavaScript, traditional functions have a few other tricks up their sleeves.

For example, functions can be used as constructors:

function Car(make, model) {
this.make = make;
this.model = model;
return this;
}
new Car('honda', 'civic');
// Produces a new `Car` instance:
// Car {make: 'honda', model: 'civic'}

Arrow functions are lightweight, low-fat, sugar-free functions. They can't be used as constructors. They don't have their own prototype.

Here's the good news: when you work with modern React, you don't have to worry about any of this stuff.

Because it's not as germane for React development, we won't go too in-depth here.

Implicitly returning objects

Let's suppose we have a function which returns an object:

function makeObject() {
return {
hi: 5,
};
}

Something sorta funny happens when we try and convert it to a short-form arrow function:

const makeObject = () => { hi: 5 };

There are two ways we could interpret this code:

  • A short-form arrow function that returns an object, { hi: 5 }
  • A long-form arrow function with a single statement, hi: 5

The problem is that curly braces ({}) serve two purposes in JavaScript: they're used for object notation, but they're also used to create blocks, like in if statements.

When curly braces follow an arrow (=>), the JS engine assumes we're creating a new block, and so we'll get a syntax error, since hi: 5 is not a valid JS statement.

If we want to implicitly return an object, we need to wrap it in parentheses:

const makeObject = () => ({ hi: 5 });

In JavaScript, parentheses can be added around any expression, to change its evaluation order. In this case, we don't care about evaluation order, we just need to make it clear that we're trying to pass an expression.

Similarly, it's common to wrap the short-form expression in parentheses when it's too long to fit on a single line:

const matchedItem = items.find(item => (
item.color === 'red' && item.size === 'large'
));

We can wrap any expression in parentheses, but we can't wrap a block in parentheses. And so, when we wrap the {} characters in parens, the engine can figure out that we're trying to create an object, not a block.